
#include <hk32f030m.h>
#include <hk32f030m_gpio.h>
#include <hk32f030m_rcc.h>
#include <perf_counter.h>

#include <pin/cm_hk030.hpp>
#include <scheduler_basic.hpp>
#include <scheduler_tick.hpp>


void nrst_switch() {
    // 切换NRST 为PA0
    RCC->APB1ENR |= RCC_APB1ENR_IOMUXEN;
    GPIOMUX->NRST_PIN_KEY = 0x5AE1;
    GPIOMUX->NRST_PA0_SEL = 1;
}


ioxx::Pin PA0_LED(GPIOA, 0);
ioxx::Pin LED(GPIOA, 2);

using TimeSource = scheduler_basic::PerfCounterMsSource;
using TimeType = TimeSource::TimeType;


/** 初始化代码
 */
void setup() {
    // "在使用进入 stop 低功耗模式时，一定要记得将 PWR 时钟打开"
    // "没有打开 PWR 时钟，则会功能异常，且不能再次烧录程序"
    RCC_APB1PeriphClockCmd(RCC_APB1Periph_PWR, ENABLE);

    ioxx::enable_gpio();
    nrst_switch();

    using namespace ioxx;

    PinInit()
        .mode(mode::out)
        .drive(drive::push_pull)
        .init(PA0_LED)
        .init(LED);


    // 启动SysTick
    NVIC_SetPriority(SysTick_IRQn, 1);
    NVIC_EnableIRQ(SysTick_IRQn);

    init_cycle_counter(false);

    __enable_irq();
}


int main(void) {
    setup();

    using namespace scheduler_basic;

    TimeCycle<TimeSource> c;

    while (1) {
        if (c.cycle(200)) {
            PA0_LED.toggle();
            LED.toggle();
        }
    }
}


extern "C" {
// 如果中断函数直接放在cpp 文件，由于C++ 编译器会修改函数名，就和中断向量表的命名不匹配了


__attribute__((used)) void SysTick_Handler() {
    user_code_insert_to_systick_handler();
}
}


#ifdef USE_FULL_ASSERT
/**
 * @brief  Reports the name of the source file and the source line number
 *         where the assert_param error has occurred.
 * @param  file: pointer to the source file name
 * @param  line: assert_param error line source number
 * @retval None
 */
void assert_failed(char* file, uint32_t line) {
    /* User can add his own implementation to report the file name and line number,
       tex: printf("Wrong parameters value: file %s on line %d\r\n", file, line) */
    /* Infinite loop */

    while (1) {
    }
}
#endif /* USE_FULL_ASSERT */
